﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Caching;

namespace PJ.Data
{
    /// <summary>
    /// OrderedFragmentPICProvider : Persist In Cache data provider
    /// </summary>
    /// <typeparam name="I">Object to provide interface type</typeparam>
    /// <typeparam name="C">Object to provide concrete class type</typeparam>
    public static class OrderedFragmentPICProvider<T>
        where T : IOrderedFragmentData
    {

        public static T GetByOrder(Dictionary<string, T> dataObjects, string parentId, double order, GetDataMode mode)
        {
            if (dataObjects == null)
                throw new ArgumentNullException("dataObjects");
            if (parentId == null || parentId.Length == 0)
                throw new ArgumentNullException("parentId");
            var query = (from d in dataObjects.Values
                         where d.OwnerId == parentId && d.Order == order
                         select d);
            if (query.Count() > 0)
                return query.Single();
            else
                if ((mode & GetDataMode.Find) == GetDataMode.Find)
                    return default(T);
                else
                    throw new DataNotFoundException("parentId, order", parentId + ", " + order.ToString());
        }
        public static double Up(Dictionary<string, T> dataObjects, string parentId, double order)
        {
            if (dataObjects == null)
                throw new ArgumentNullException("dataObjects");
            if (parentId == null || parentId.Length == 0)
                throw new ArgumentNullException("parentId");
            T item = GetByOrder (dataObjects, parentId, order, GetDataMode.Default);
            var nextItems = (from d in dataObjects.Values where d.OwnerId == parentId && d.Order > order select d.Order);
            if (nextItems.Count() != 0)
                item.Order = item.Order + (nextItems.Min() - item.Order) / 2.0;
            return item.Order;
        }

        public static double Down(Dictionary<string, T> dataObjects, string parentId, double order)
        {
            if (dataObjects == null)
                throw new ArgumentNullException("dataObjects");
            if (parentId == null || parentId.Length == 0)
                throw new ArgumentNullException("parentId");
            T item = GetByOrder(dataObjects, parentId, order, GetDataMode.Default);
            var previousItems = (from d in dataObjects.Values
                                 where d.OwnerId == parentId && d.Order < order
                                 select d.Order);
            if (previousItems.Count() != 0)
                item.Order = item.Order - (item.Order - previousItems.Max()) / 2.0;
            return item.Order;
        }

        public static bool IsFirst(Dictionary<string, T> dataObjects, string parentId, double order)
        {
            if (dataObjects == null)
                throw new ArgumentNullException("dataObjects");
            if (parentId == null || parentId.Length == 0)
                throw new ArgumentNullException("parentId");
            return (from d in dataObjects.Values where d.OwnerId == parentId && d.Order < order 
                    select d.Order).Count() == 0;
        }

        public static bool IsLast(Dictionary<string, T> dataObjects, string parentId, double order)
        {
            if (dataObjects == null)
                throw new ArgumentNullException("dataObjects");
            if (parentId == null || parentId.Length == 0)
                throw new ArgumentNullException("parentId");
            return (from d in dataObjects.Values where d.OwnerId == parentId && d.Order > order 
                    select d.Order).Count() == 0;
        }


        internal static bool OrderExists(Dictionary<string, T> dataObjects, string parentId, double order)
        {
            return (from d in dataObjects.Values
                    where d.OwnerId == parentId && d.Order == order
                    select d).Count() != 0;
        }
    }
}
